{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import gym\n",
    "import numpy as np\n",
    "from gym import spaces\n",
    "\n",
    "class CardGameEnv(gym.Env):\n",
    "    def __init__(self):\n",
    "        super(CardGameEnv, self).__init__()\n",
    "        \n",
    "        # 定义 observation_space，这里以 Dict 为例\n",
    "        self.observation_space = spaces.Dict({\n",
    "            \"hand\": spaces.Box(low=0, high=1, shape=(160,), dtype=np.float32),\n",
    "            \"deck\": spaces.Box(low=0, high=1, shape=(160,), dtype=np.float32),\n",
    "            \"valid_actions\": spaces.MultiBinary(160)\n",
    "        })\n",
    "        \n",
    "        self.state = np.zeros(160)  # 表示手牌状态：1 表示手上有，0 表示没有\n",
    "        self.deck = np.ones(160)    # 简单示例：牌堆里所有牌初始都有\n",
    "        self.valid_actions = np.copy(self.state)\n",
    "        self.done = False\n",
    "        self.reset()\n",
    "\n",
    "    def reset(self):\n",
    "        \"\"\" 初始化游戏状态 \"\"\"\n",
    "        self.state = np.zeros(160)\n",
    "        # 假设随机选5张牌在手上\n",
    "        hand_indices = np.random.choice(160, size=5, replace=False)\n",
    "        self.state[hand_indices] = 1\n",
    "        # 同时更新牌堆和有效动作（这里只做简单示例）\n",
    "        self.deck = np.ones(160)\n",
    "        self.valid_actions = np.copy(self.state)\n",
    "        \n",
    "        # 返回一个结构化的观测信息\n",
    "        return {\"hand\": self.state, \"deck\": self.deck, \"valid_actions\": self.valid_actions}\n",
    "\n",
    "    def update_valid_actions(self):\n",
    "        \"\"\" 根据当前手牌更新可行的动作 mask \"\"\"\n",
    "        self.valid_actions = np.copy(self.state)\n",
    "    \n",
    "    def step(self, action_index):\n",
    "        \"\"\"\n",
    "        处理 AI 选择的动作\n",
    "        \"\"\"\n",
    "        # 假设 action_index 是当前合法动作的索引（我们用 mask 过滤后的结果）\n",
    "        # 为了简单示例，我们认为 action_index 直接对应具体卡牌的索引\n",
    "        if self.state[action_index] != 1:  # 如果这张牌不在手上，非法动作\n",
    "            reward = -1\n",
    "        else:\n",
    "            # 合法出牌\n",
    "            self.state[action_index] = 0  # 移除这张牌\n",
    "            reward = self.compute_reward(action_index)\n",
    "        \n",
    "        # 更新合法动作\n",
    "        self.update_valid_actions()\n",
    "        self.done = self.check_game_end()\n",
    "        \n",
    "        # 返回最新观测\n",
    "        obs = {\"hand\": self.state, \"deck\": self.deck, \"valid_actions\": self.valid_actions}\n",
    "        return obs, reward, self.done, {}\n",
    "\n",
    "    def compute_reward(self, action):\n",
    "        \"\"\" 奖励规则示例 \"\"\"\n",
    "        if action in [10, 50, 100]:  # 假设这些索引代表关键牌\n",
    "            return 5\n",
    "        return 1\n",
    "\n",
    "    def check_game_end(self):\n",
    "        \"\"\" 判断游戏是否结束 \"\"\"\n",
    "        return np.sum(self.state) == 0  # 如果手牌打完，游戏结束\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "charlatan",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.11.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
